home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / bash / bash_108 / src_d2.zoo / bash-d2.zoo / libgcc / symdir.c < prev   
Encoding:
C/C++ Source or Header  |  1991-09-03  |  7.1 KB  |  392 lines

  1. /*
  2.  * _read_symdir(), _write_symdir(), _free_symdir(): routines for
  3.  * reading/writing the special directories used for symbolic links.
  4.  * If symbolic links were not set active in UNIXMODE, then theses
  5.  * routines are no-ops.
  6.  *
  7.  * Written by Eric R. Smith and placed in the public domain. Use
  8.  * at your own risk.
  9.  */
  10.  
  11. #include <stdio.h>
  12. #include <osbind.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <errno.h>
  16. #include "symdir.h"
  17.  
  18. #ifndef NAME_MAX
  19. #  include <limits.h>
  20. #endif
  21.  
  22. #ifndef _LIB_NAME_MAX
  23. #  define _LIB_NAME_MAX NAME_MAX
  24. #endif
  25.  
  26. /*
  27.  * utility routine to provide buffered I/O for _read_symdir()
  28.  */
  29.  
  30. #define ResetFgetc() Fgetc(-1)
  31.  
  32. static int Fgetc(fd)
  33.     int fd;
  34. {
  35.     static unsigned char buf[BUFSIZ], *pos;
  36.     static int siz = 0;
  37.  
  38.     if (fd < 0) {
  39.         siz = 0; pos = buf; return 0;
  40.     }
  41.  
  42.     if (siz == 0) {
  43.         siz = Fread(fd, BUFSIZ, buf);
  44.         pos = buf;
  45.         if (siz <= 0) {
  46.             siz = 0; pos = buf; return -1;
  47.         }
  48.     }
  49.     siz--;
  50.     return *pos++;
  51. }
  52.  
  53.  
  54. /*
  55.  * Routines for keeping a cache of recently used symbolic directories.
  56.  * The last 8 directories accessed are kept cached; this really helps
  57.  * the directory searches in unx2dos, but does eat some memory.
  58.  *
  59.  * entries are added to the cache by _free_symdir, and removed if they
  60.  * fall off the end, or if they're retrieved by a subsequent _read_symdir.
  61.  *
  62.  * IMPLICIT ASSUMPTION: the same directory is never open more than once.
  63.  */
  64.  
  65. #define CACHESIZE 8
  66.  
  67. static SYMDIR *in_cache;
  68.  
  69. static
  70. SYMDIR *_cache_lookup(pth)
  71.     const char *pth;
  72. {
  73.     SYMDIR *prev = 0, *cur = in_cache;
  74.  
  75.     while (cur) {
  76.         if (!strcmp(cur->s_pth, pth)) {
  77. /* remove from cache */
  78.             if (prev)
  79.                 prev->s_nxt = cur->s_nxt;
  80.             else
  81.                 in_cache = cur->s_nxt;
  82.             cur->s_nxt = 0;
  83.             return cur;
  84.         }
  85.         prev = cur; cur = cur->s_nxt;
  86.     }
  87.     return 0;
  88. }
  89.  
  90. static
  91. void
  92. _cache_add(cur)
  93.     SYMDIR *cur;
  94. {
  95.     SYMDIR *nxt = 0;
  96.     SYMENTRY *dir, *old;
  97.  
  98.     int count = 0;
  99.  
  100.     cur->s_nxt = in_cache;
  101.     in_cache = cur;
  102.     while (cur) {
  103.         nxt = cur->s_nxt;
  104.         ++count;
  105.         if (count == CACHESIZE)
  106.             cur->s_nxt = 0;
  107.         else if (count > CACHESIZE) {
  108.             dir = cur->s_dir;
  109.             while (dir) {
  110.                 old = dir;
  111.                 dir = dir->next;
  112.                 free(old);
  113.             }
  114.             free(cur->s_pth);
  115.             free(cur);
  116.         }
  117.         cur = nxt;
  118.     }
  119. }
  120.  
  121. /*
  122.  * free a symbolic directory. Note that unx2dos is expecting the entries
  123.  * to be accessible, i.e. it knows that we're caching at least 1 directory.
  124.  * If this ever changes, change unx2dos.
  125.  */
  126.  
  127. void _free_symdir(dir)
  128.     SYMDIR *dir;
  129. {
  130.     if (dir)
  131.         _cache_add(dir);
  132. }
  133.  
  134. /*
  135.  * read in the symbolic directory corresponding to "path".
  136.  * the symdir must be removed from the cache, since it may
  137.  * be modified and written back via _write_symdir
  138.  */
  139.  
  140. SYMDIR *_read_symdir(path)
  141.     char *path;
  142. {
  143.     char dirname[FILENAME_MAX], tmp[2*FILENAME_MAX], *p;
  144.     int fd, c;
  145.     SYMENTRY *old, *new;
  146.     SYMDIR *dir;
  147.  
  148. /* check that symbolic links are active */
  149.     if (!_lOK) {
  150.         errno = EINVAL;
  151.         return NULL;
  152.     }
  153.  
  154.     strcpy(dirname, path);
  155.     strcat(dirname, "\\");
  156.     strcat(dirname, _lDIR);
  157.  
  158.     if (dir = _cache_lookup(dirname))
  159.         return dir;
  160.  
  161.     ResetFgetc();
  162.     fd = Fopen(dirname, 0);
  163.     if (fd < 0 && fd != -ENOENT) {
  164.         errno = -fd;
  165.         return NULL;
  166.     }
  167.  
  168.     dir = (SYMDIR *)malloc(sizeof(SYMDIR)+strlen(tmp)+1);
  169.     if (dir == NULL) {
  170.         errno = ENOMEM;
  171.         return dir;
  172.     }
  173.     dir->s_pth = strdup(dirname);
  174.     if (!dir->s_pth)
  175.         return NULL;
  176.     dir->s_nxt = 0;
  177.  
  178.     old = NULL;
  179.     if (fd == -ENOENT) goto done_directory;
  180.  
  181.     p = tmp;
  182.     while ( (c = Fgetc(fd)) >= 0 ) {
  183.         if (c == '\r') continue;
  184.         if (c == '\n') {
  185.             *p++ = 0;
  186.             new= (SYMENTRY *)malloc(sizeof(SYMENTRY)+strlen(tmp)+1);
  187.             if (new == 0) break;
  188.             strcpy(new->linkname, tmp);
  189.             new->linkto = new->linkname;
  190.             for (p = new->linkname; *p; p++) {
  191.                 if (*p == '\t') {
  192.                     *p++ = 0;
  193.                     new->linkto = p;
  194.                     break;
  195.                 }
  196.             }
  197. /*
  198.  * Now we should check for any further fields, such as "flags"
  199.  * it is very important that we save *all* the characters that were given
  200.  * in the flags field, as well as setting the bits we understand.
  201.  * That way, programs remain compatible with future versions of the
  202.  * standard.
  203.  */
  204.             for (;*p;p++) {
  205.                 if (*p == '\t') {
  206.                     *p++ = 0;
  207.                     break;
  208.                 }
  209.             }
  210.             new->cflags = p; /* save pointer to flag characters */
  211.             new->flags = 0;
  212.             for (;*p;p++) {
  213.                 if (*p == 'A')
  214.                     new->flags |= SD_AUTO;
  215.             }
  216.             new->next = old;
  217.             old = new;
  218.             p = tmp;
  219.         }
  220.         else
  221.             *p++ = c;
  222.     }
  223.     (void)Fclose(fd);
  224.  
  225. done_directory:
  226.     dir->s_dir = old;
  227.     return dir;
  228. }
  229.  
  230. /*
  231.  * write a symbolic directory out onto a path
  232.  */
  233.  
  234. int _write_symdir(path, dir)
  235.     char *path;
  236.     SYMDIR *dir;
  237. {
  238.     SYMENTRY *new;
  239.     int fd, r;
  240.     char dirname[FILENAME_MAX];
  241.  
  242. /* check to see that symbolic links are OK */
  243.     if (!_lOK)
  244.         return -EINVAL;
  245.  
  246.     strcpy(dirname, path);
  247.     strcat(dirname, "\\");
  248.     strcat(dirname, _lDIR);
  249.  
  250.     fd = Fcreate(dirname, 0);
  251.     if (fd < 0) {
  252.         return fd;
  253.     }
  254.  
  255.     for (new = dir->s_dir; new; new = new->next) {
  256.         (void)Fwrite(fd, strlen(new->linkname), new->linkname);
  257.         (void)Fwrite(fd, 1L, "\t");
  258.         (void)Fwrite(fd, strlen(new->linkto), new->linkto);
  259.         if (new->cflags[0]) {
  260.             (void)Fwrite(fd, 1L, "\t");
  261.             (void)Fwrite(fd, strlen(new->cflags), new->cflags);
  262.         }
  263.         r = Fwrite(fd, 1L, "\n");
  264.         if (r <= 0) {
  265.             (void)Fclose(fd);
  266.             return r;
  267.         }
  268.     }
  269.  
  270.     (void)Fclose(fd);
  271.     return 0;
  272. }
  273.  
  274. /*
  275.  * _symdir_lookup, _make_symlink: utility routines that are needed in
  276.  * various places
  277.  */
  278.  
  279. /*
  280.  * return the symbolic directory entry for "name", or NULL if it is not
  281.  * found
  282.  */
  283.  
  284. SYMENTRY *
  285. _symdir_lookup(dir, name)
  286.     SYMDIR *dir;
  287.     const char *name;
  288. {
  289.     SYMENTRY *ent;
  290.  
  291.     if (!dir) return 0;
  292.     for (ent = dir->s_dir; ent; ent = ent->next) {
  293.         if (!strcmp(ent->linkname, name))
  294.             return ent;
  295.     }
  296.     return 0;
  297. }
  298.  
  299. /*
  300.  * _make_autolink(dosname, source): make an "automatic" symbolic link,
  301.  * with name "source", to the file whose full canonical dos pathname is in
  302.  * "dosname". Returns 1 if link made, 0 if not. It checks the _lAUTO
  303.  * flag, so parent functions don't have to. Parents are responsible
  304.  * for dealing with any conflicts with existing files.
  305.  */
  306.  
  307. int _make_autolink(dosname, source)
  308.     char *dosname, *source;
  309. {
  310.     char path[FILENAME_MAX], oldname[_LIB_NAME_MAX];
  311.     char *s, *p;
  312.     SYMDIR *dir;
  313.     SYMENTRY *d;
  314.  
  315.     if (!_lAUTO)
  316.         return 0;
  317.  
  318.     strcpy(path, dosname);
  319.     if ((p = strrchr(path, '\\'))) {
  320.         *p++ = 0;
  321.         dos2unx(p, oldname);
  322.     } else {
  323.         dos2unx(path, oldname);
  324.         path[0] = 0;
  325.     }
  326.  
  327.     if (!(dir = _read_symdir(path)))
  328.         return 0;
  329.     d = (SYMENTRY *)
  330.         malloc(sizeof(SYMENTRY)+strlen(source)+strlen(oldname)+4);
  331.     if (d == 0) {
  332.         errno = ENOMEM;
  333.         return -1;
  334.         _free_symdir(dir);
  335.     }
  336. /*
  337.  * now set up the fields; remember to set the character flags (cflags) as well!
  338.  */
  339.     strcpy(d->linkname, source);
  340.     for (s = d->linkname; *s; s++)
  341.         ;
  342.     ++s;
  343.     d->linkto = s;
  344.     strcpy(s, oldname);
  345.     for (; *s; s++)
  346.         ;
  347.     ++s;
  348.     strcpy(s, "A");        /* AUTO flag */
  349.     d->cflags = s;
  350.     d->flags = SD_AUTO;
  351.     d->next = dir->s_dir;
  352.     dir->s_dir = d;
  353.     _write_symdir(path, dir);
  354.     return 1;
  355. }
  356.  
  357.  
  358. /**
  359.  ** (sjk)++ Added a delete symdir cache from E. Roeder's library.
  360.  **/
  361.  
  362. static
  363. void
  364. _del_dir(cur)
  365.     SYMDIR *cur;
  366. {
  367.     SYMENTRY *dir, *old;
  368.  
  369.     dir = cur->s_dir;
  370.     while (dir) {
  371.         old = dir;
  372.         dir = dir->next;
  373.         free(old);
  374.     }
  375.     free(cur->s_pth);
  376.     free(cur);
  377. }
  378.  
  379. void
  380. _del_symdir_cache()
  381. {
  382.     SYMDIR *cur = in_cache, *nxt = 0;
  383.  
  384.     while (cur) {
  385.         nxt = cur->s_nxt;
  386.         _del_dir(cur);
  387.         cur = nxt;
  388.     }
  389.     in_cache = 0;
  390. }
  391.  
  392.